-
Notifications
You must be signed in to change notification settings - Fork 88
Improve HalfEdgeTopology(::Vector{<:Connectivity})
correctness
#1194
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve HalfEdgeTopology(::Vector{<:Connectivity})
correctness
#1194
Conversation
The code/algorithm doesn't actually check for counter-clockwise-ness, it only knows whether something has an inconsistent orientation with previously added elements (ultimately going back to whichever element was added first--whose orientation was never checked)
2a6d072
to
16aa7c4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @halleysfifthinc ! Left a few minor comments. I can review again after we get green tests.
Co-authored-by: Júlio Hoffimann <julio.hoffimann@gmail.com>
Co-authored-by: Júlio Hoffimann <julio.hoffimann@gmail.com>
Co-authored-by: Júlio Hoffimann <julio.hoffimann@gmail.com>
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #1194 +/- ##
==========================================
+ Coverage 88.31% 88.39% +0.07%
==========================================
Files 196 196
Lines 6094 6133 +39
==========================================
+ Hits 5382 5421 +39
Misses 712 712 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
8f116fa
to
f84346f
Compare
Benchmarking procedure same as previously described, using Quads only:
Quads and tris:
|
Thank you for the updates @halleysfifthinc. I am planning to review a couple of PRs in CoordRefSystems.jl, Meshes.jl and GeoIO.jl this week. |
@halleysfifthinc the tests were failing locally for me, falling in the |
Before or after the readability changes in dab47eb? Tests are consistently passing for me before that commit, and also consistently pass after I sidestep the base Julia bug. 🤞 nothing turns up in this CI run |
Almost sure it was before the changes. I did run the tests locally, then made the changes. |
Hmmm. Yesterday, I did see a test failure once before the readability commit, but I'm not able to replicate that today. I wonder if it was user error on my part (e.g. I wasn't actually on the right commit, etc). I have been running one of the previously failing tests in an infinite loop for >20mins now and have not triggered any more errors. (I also have been running with these patches [with the |
I confirm that all tests pass locally 💯 Will review the test changes one by one now, before assessing the performance improvements 👍🏽 |
All test changes are perfect 💯 I will benchmark the PR against the master branch now... |
I confirm a speedup of approximately 2x when |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes nondeterministic ordering and orientation bugs in the HalfEdgeTopology
constructor and updates related tests.
- Rewrites half-edge pairing logic to produce deterministic, element‐ordered halves and correctly handle element orientation.
- Introduces helper functions (
anyhalf
,anyhalfclaimed
) and refactorsadjsort
placement. - Adjusts test expectations throughout
test/toporelations.jl
andtest/topologies.jl
to match the new ordering/orientation behavior.
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
File | Description |
---|---|
test/toporelations.jl | Updated expected boundary/coboundary tuples to reflect new half-edge order. |
test/topologies.jl | Added invariants for half-edge prev /next , updated element ordering tests. |
src/topologies/halfedge.jl | Overhauled HalfEdgeTopology constructor, added helper functions, removed old inline adjsort . |
Comments suppressed due to low confidence (1)
src/topologies/halfedge.jl:373
- [nitpick] The name
anyhalf
is ambiguous. Consider renaming to something likehas_shared_halfedge
andanyhalfclaimed
tohas_claimed_halfedge
for clarity.
function anyhalf(inds, half4pair)
@JoshuaLampert do you have any additional comment before we merge this? I know it is a very tricky algorithm to follow, so don't feel any pressure to review in detail. Any bird's-eye review would be nice given the sensitivity of these changes 🙂 |
The test that is failing consistently in MacOS is unrelated to the changes in this PR. We need to increase the threshold in a separate PR later. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the contribution, @halleysfifthinc! I had a quick look and didn't find any issue standing out. But, as you suggested @juliohm, I didn't look at the algorithm, but had only an abstract view. Generally, as someone who only has a very rough idea of what the code is supposed to do, I find the code quite hard to read, but I guess there is not much to do against this. I was wondering whether this counts as breaking change because, IIUC, it changes the ordering. Or was the ordering nothing to rely on before anyway and therefore this change can be done in a non-breaking way?
The ordering of vertices in Originally I thought of releasing this as a patch release to upstream the performance improvements throughout the ecosystem, but if you guys feel that this has the potential to break code, we can go with a minor release. |
Thank you all for the valuable contributions! Merging another important fix and speedup 🚀 👏🏽 |
I would be consider this a non-breaking bugfix, as the previous indices were indisputably (IMO) incorrect (albeit, consistently so). Any code relying on the previous orderings is potentially also incorrect, and therefore implicitly already broken. |
Very good point. This PR also fixes a bug so it would be a good idea to
propagate the fix.
Em ter., 20 de mai. de 2025, 17:57, Allen Hill ***@***.***>
escreveu:
… *halleysfifthinc* left a comment (JuliaGeometry/Meshes.jl#1194)
<#1194 (comment)>
if you guys feel that this has the potential to break code, we can go with
a minor release
I would be consider this a non-breaking bugfix, as the previous indices
were indisputably (IMO) incorrect (albeit, consistently so). Any code
relying on the previous orderings is potentially also incorrect, and
therefore implicitly already broken.
—
Reply to this email directly, view it on GitHub
<#1194 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAZQW3MYQJI75WQ4ZELXJ4L27OJL3AVCNFSM6AAAAAB5BPSIEGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDQOJVHAYTIMBXGI>
.
You are receiving this because you modified the open/close state.Message
ID: ***@***.***>
|
It's fine with me to not consider it as breaking. |
This PR reveals/fixes a couple of bugs in the
HalfEdgeTopology
constructor.Dict
's are unordered, so constructing thehalves::Vector{Tuple{HalfEdge,HalfEdge}}
by iterating throughhalf4pair
pairs produces a roughly random order (by element) for halves.Meshes.jl/src/topologies/halfedge.jl
Line 220 in 3a3d0e3
loop
. (Cause of most/all? test failures.)master
state of the function can lead to non-closed edge loops, such that theloop
function never terminates and allocates memory until Julia is OOM killed1.CCW
) was misleading, as actual element orientation isn't checked (and cannot be without actual vertices afaict?). Also, when there are multiple unconnected components (which I believe is still valid under a 2-manifold?) the orientation consistency checks don't/can't cross the disconnection, leading to further potential mismatches between the nameCCW
and reality. I renamed it to make this clearer.The cause of most of the current test failures are due to changing to the
halves
construction to be element ordered. I believe this is more correct, and that any stable/consistent edge indices with the previous version are because the hashing algorithm in Base has not been changed between Julia versions (that will no longer be true after 1.13 with JuliaLang/julia#57509).Another cause of test failures is a change to the reverse index iteration, which now ensures that the first index returned by
loop
(which affects several downstream dependent functions) is either:With regard to sorting and orientation consistency, the PR is correct (no infinite memory use) even for incorrectly- or unsorted elements when called with
sort=false
, but the edge indices will/may change betweensort=false
andsort=true
.If you agree with this PR's general direction. I will update the tests and share benchmarks.
Footnotes
In my code, I am redefining
loop
similar to the given example, but using a ScopedValue so that the maximum number of edges can be changed from outside the function if needed. I'm happy to share/submit that if you are interested, but I realize that such a solution might be too limiting generally to be added to the library. ↩